import type { MusicStoreRecord } from '@/types/music'

// ========== Music Store ========= //
import Dexie from 'dexie'

import type { EntityTable } from 'dexie'
// ======== IndexedDB Store ======== //
// ====== Music Store ====== //
/**
 * 音乐存储
 * @store 存储表
 * @getMusicList 获取音乐列表
 * @getMusic 获取音乐
 * @saveMusic 保存音乐
 * @extends Dexie
 */
class MusicStore extends Dexie {

  // 存储表
  store: EntityTable<MusicStoreRecord>

  constructor(databaseName: string, tableName: string, version: number) {
    super(databaseName)
    this.version(version).stores({
      [tableName]: 'union_key, id, name, source, album, artist, br',
    })
    this.store = this.table(tableName)
  }

  /**
   * 获取已下载的音乐列表
   * @returns MusicStoreRecord[]
   */
  async getMusicList(): Promise<MusicStoreRecord[]> {
    return new Promise((resolve, _) => {
      this.store.where('union_key').notEqual(0).toArray().then((data: MusicStoreRecord[]) => {
        if (data) {
          resolve(data)
        } else {
          console.warn('Could not find downloaded music in indexedDB')
          resolve([])
        }
      })
    })
  }

  /**
   * 获取指定音乐
   * @param union_key 音乐联合主键
   * @returns
   */
  async getMusic(union_key: number | string): Promise<MusicStoreRecord | undefined> {
    return new Promise((resolve, _) => {
      this.store.where('union_key').equals(union_key).first().then((data: MusicStoreRecord | undefined) => {
        if (!data) {
          console.warn('Could not find downloaded music in indexedDB')
        }
        resolve(data)
      })
    })
  }

  /**
   * 保存音乐
   * @param record
   * @returns
   */
  async saveMusic(record: MusicStoreRecord) {
    return new Promise((resolve, _) => {
      this.store.put(record).then(() => {
        console.log(`保存成功：【${record.artist?.join(' / ')}-${record.name}】`)
        resolve(record)
      })
    })
  }
}

export const musicStore = new MusicStore('music', 'downloaded-music', Number(import.meta.env.VITE_INDEXEDDB_DATABASE_VERSION))

// ======== Zustand Store ======== //
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

// ====== Globally Download Music Method ====== //

export type DownloadMusicMethodParams = {
  musicInfo: MusicStoreRecord,
  quality: string,
  provider: string
}
export type DownloadMusicMethodState = {
  downloadMusicMethod: ((musicInfo: MusicStoreRecord, quality: string, provider: string) => Promise<void>) | null
}

export type DownloadMusicMethodActions = {
  setDownloadMusicMethod: (downloadMusicMethod: DownloadMusicMethodState['downloadMusicMethod']) => void
}

export const useDownloadMusicMethodStore = create<DownloadMusicMethodState & DownloadMusicMethodActions>()(
  persist(
    (set) => ({
      downloadMusicMethod: async () => {
        console.error('downloadMusicMethod is not set')
        return undefined
      },
      setDownloadMusicMethod: (downloadMusicMethod: DownloadMusicMethodState['downloadMusicMethod'] | null) => set(() => ({ downloadMusicMethod })),
    }),
    {
      name: 'downloadMusicMethod',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

// ====== Globally Play Music Method ====== //

export type PlayMusicMethodState = {
  playMusicMethod: (id: number | string, source: string, quality: string) => void
}

export type PlayMusicMethodActions = {
  setPlayMusicMethod: (playMusicMethod: PlayMusicMethodState['playMusicMethod']) => void
}

export const usePlayMusicMethodStore = create<PlayMusicMethodState & PlayMusicMethodActions>()(
  persist(
    (set) => ({
      playMusicMethod: async () => {
        console.error('playMusicMethod is not set')
      },
      setPlayMusicMethod: (playMusicMethod) => set(() => ({ playMusicMethod }))
    }),
    {
      name: 'playMusicMethod',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

// ====== Playing Music State ====== //

export type PlayingMusicState = {
  state: {
    id: number | string
    name: string
    artist: string
    source: string
    quality: string
    playbackTime: number
    duration: number
    currentLyricLine: number
  }
}

export type PlayingMusicActions = {
  setPlayingMusic(playingMusic: PlayingMusicState['state']): void
  setPlayingMusic(callback: (playingMusic: PlayingMusicState['state']) => PlayingMusicState['state']): void
}

export const usePlayingMusicStore = create<PlayingMusicState & PlayingMusicActions>()(
  persist(
    (set, get) => ({
      state: {
        id: 0,
        name: '',
        artist: '',
        playing: false,
        source: '',
        quality: '',
        playbackTime: 0,
        duration: 0,
        currentLyricLine: 0,
      },
      setPlayingMusic: (
        params: PlayingMusicState['state'] | ((playingMusic: PlayingMusicState['state']) => PlayingMusicState['state'])
      ) => {
        if (typeof params === 'function') {
          set(() => ({ state: params(get().state) }))
        } else {
          set(() => ({ state: params }))
        }
      }
    }),
    {
      name: 'playingMusic',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

// ====== Music Player State ====== //

export type MusicPlayerState = {
  volume: number
  playing: boolean
  size: 'sm' | 'md' | 'full'
  playList: MusicStoreRecord['id'][]
}

export type MusicPlayerActions = {
  setVolume: (volume: number) => void
  setPlaying: (playing: boolean) => void
  setSize: (size: 'sm' | 'md' | 'full') => void
  setPlayList(playList: MusicStoreRecord['id'][]): void
  setPlayList(callback: ((playList: MusicStoreRecord['id'][]) => MusicStoreRecord['id'][])): void
}

export const useMusicPlayerStore = create<MusicPlayerState & MusicPlayerActions>()(
  persist(
    (set, get) => ({
      volume: 1,
      playing: false,
      size: 'md',
      playList: [],
      setVolume: (volume) => set(() => ({ volume })),
      setPlaying: (playing) => set(() => ({ playing })),
      setSize: (size) => set(() => ({ size })),
      setPlayList: (playList) => {
        if (typeof playList === 'function') {
          set(() => ({ playList: playList(get().playList) }))
        } else {
          set(() => ({ playList }))
        }
      }
    }),
    {
      name: 'musicPlayer',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

// ====== Download Music Settings ======

// ==== Download Path ====
type DownloadPathStore = {
  downloadPath: string
}
type DownloadPathStoreActions = {
  setDownloadPath: (downloadPath: string) => void
}
export const useDownloadPathStore = create<DownloadPathStore & DownloadPathStoreActions>()(
  persist(
    (set) => ({
      downloadPath: '',
      setDownloadPath: (downloadPath) => set(() => ({ downloadPath })),
    }),
    {
      name: 'downloadPath',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

// ==== Download Quality ====
type DownloadQualityStore = {
  downloadQuality: string
}
type DownloadQualityStoreActions = {
  setDownloadQuality: (downloadQuality: string) => void
}
export const useDownloadQualityStore = create<DownloadQualityStore & DownloadQualityStoreActions>()(
  persist(
    (set) => ({
      downloadQuality: '320k',
      setDownloadQuality: (downloadQuality) => set(() => ({ downloadQuality }))
    }),
    {
      name: 'downloadQuality',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

// ==== Download Provider ====
type DownloadProviderStore = {
  downloadProvider: string
}
type DownloadProviderStoreActions = {
  setDownloadProvider: (downloadProvider: string) => void
}
export const useDownloadProviderStore = create<DownloadProviderStore & DownloadProviderStoreActions>()(
  persist(
    (set) => ({
      downloadProvider: 'ikun',
      setDownloadProvider: (downloadProvider) => set(() => ({ downloadProvider }))
    }),
    {
      name: 'downloadProvider',
      storage: createJSONStorage(() => localStorage),
    }
  )
)